package com.yc.cloud.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yc.cloud.admin.service.DashboardService;
import com.yc.cloud.admin.vo.dashboard.*;
import com.yc.cloud.api.enums.AlarmLevelEnum;
import com.yc.cloud.api.enums.AlarmStatusEnum;
import com.yc.cloud.api.enums.HWDeviceStatus;
import com.yc.cloud.entity.AlarmRecord;
import com.yc.cloud.entity.AlgAlgorithm;
import com.yc.cloud.entity.HwDevice;
import com.yc.cloud.mapper.AlarmRecordMapper;
import com.yc.cloud.mapper.AlgAlgorithmMapper;
import com.yc.cloud.mapper.HwDeviceMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.Arrays;

/**
 * <p>
 * 仪表盘服务实现类
 * </p>
 *
 * @author kinggu
 * @since 2025-07-30
 */
@Service
@Slf4j
public class DashboardServiceImpl implements DashboardService {

    @Resource
    private AlarmRecordMapper alarmRecordMapper;

    @Resource
    private HwDeviceMapper hwDeviceMapper;

    @Resource
    private AlgAlgorithmMapper algAlgorithmMapper;

    @Override
    public AlarmEfficiencyVO getAlarmEfficiency() {
        // 定义已处理状态列表
        List<Byte> processedStatuses = Arrays.asList(
                AlarmStatusEnum.CLOSED.getValue(),
                AlarmStatusEnum.FALSE_ALARM.getValue()
        );

        // 计算平均响应时间（秒）
        Double averageResponseTime = alarmRecordMapper.selectAverageResponseTime(processedStatuses);

        // 计算今日处理率
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        long todayTotal = alarmRecordMapper.selectCount(
                new QueryWrapper<AlarmRecord>()
                        .ge(AlarmRecord.AlarmTime, todayStart)
        );
        long todayProcessed = alarmRecordMapper.selectCount(
                new QueryWrapper<AlarmRecord>()
                        .ge(AlarmRecord.AlarmTime, todayStart)
                        .in(AlarmRecord.Status, processedStatuses)
        );
        double todayProcessRate = todayTotal > 0 ? (double) todayProcessed / todayTotal * 100 : 0;

        // 计算紧急告警处理率
        long emergencyTotal = alarmRecordMapper.selectCount(
                new QueryWrapper<AlarmRecord>()
                        .eq(AlarmRecord.Level, AlarmLevelEnum.EMERGENCY.getValue())
        );
        long emergencyProcessed = alarmRecordMapper.selectCount(
                new QueryWrapper<AlarmRecord>()
                        .eq(AlarmRecord.Level, AlarmLevelEnum.EMERGENCY.getValue())
                        .in(AlarmRecord.Status, processedStatuses)
        );
        double emergencyProcessRate = emergencyTotal > 0 ? (double) emergencyProcessed / emergencyTotal * 100 : 0;

        return AlarmEfficiencyVO.builder()
                .averageResponseTime(averageResponseTime)
                .todayProcessRate(todayProcessRate)
                .emergencyProcessRate(emergencyProcessRate)
                .build();
    }

    @Override
    public List<RealtimeAlarmVO> getRealtimeAlarms(Integer limit) {
        // 查询最近的告警记录
        List<AlarmRecord> records = alarmRecordMapper.selectList(
                new QueryWrapper<AlarmRecord>()
                        .orderByDesc(AlarmRecord.AlarmTime)
                        .last("LIMIT " + limit)
        );

        // 转换为VO
        return records.stream().map(record -> {
            RealtimeAlarmVO vo = new RealtimeAlarmVO();
            vo.setId(record.getId());
            vo.setLocation(record.getDeviceLocation());
            vo.setAlarmName(record.getAlarmName());
            vo.setAlarmTime(record.getAlarmTime());
            vo.setStatus(record.getStatus());
            
            // 设置告警状态名称
            AlarmStatusEnum statusEnum = AlarmStatusEnum.getByValue(record.getStatus());
            if (statusEnum != null) {
                vo.setStatusName(statusEnum.getDesc());
            }
            
            // 设置告警图片URL
            // 假设有一个方法可以根据文件ID获取URL
            String imageUrl = getFileUrlById(record.getAlarmMarkedImageFileId());
            if (imageUrl == null) {
                imageUrl = getFileUrlById(record.getAlarmImageFileId());
            }
            vo.setImageUrl(imageUrl);
            
            return vo;
        }).collect(Collectors.toList());
    }
    
    /**
     * 根据文件ID获取URL
     * 这里只是一个示例，实际实现应该调用您的文件服务
     */
    private String getFileUrlById(String fileId) {
        if (fileId == null || fileId.isEmpty()) {
            return null;
        }
        // 这里应该是调用您的文件服务获取URL的逻辑
        // 例如：return ossFileService.getFileUrl(fileId);
        return "/api/files/" + fileId;
    }

    @Override
    public AlarmTrendVO getAlarmTrend() {
        // 获取24小时的时间点
        List<String> timePoints = new ArrayList<>();
        List<Long> counts = new ArrayList<>();
        
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime start = now.minusHours(24);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
        
        // 按小时统计告警数量
        for (int i = 0; i < 24; i++) {
            LocalDateTime hourStart = start.plusHours(i);
            LocalDateTime hourEnd = hourStart.plusHours(1);
            
            timePoints.add(hourStart.format(formatter));
            
            long count = alarmRecordMapper.selectCount(
                    new QueryWrapper<AlarmRecord>()
                            .ge(AlarmRecord.AlarmTime, hourStart)
                            .lt(AlarmRecord.AlarmTime, hourEnd)
            );
            counts.add(count);
        }
        
        AlarmTrendVO vo = new AlarmTrendVO();
        vo.setTimePoints(timePoints);
        vo.setCounts(counts);
        return vo;
    }

    @Override
    public KeyMetricsVO getKeyMetrics() {
        // 设备总数
        long totalDevices = hwDeviceMapper.selectCount(null);
        
        // 在线设备数
        long onlineDevices = hwDeviceMapper.selectCount(
                new QueryWrapper<HwDevice>()
                        .eq(HwDevice.Status, HWDeviceStatus.ONLINE.getCode())
        );
        
        // 在线率
        double onlineRate = totalDevices > 0 ? (double) onlineDevices / totalDevices * 100 : 0;
        
        // 今日告警数
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        long todayAlarms = alarmRecordMapper.selectCount(
                new QueryWrapper<AlarmRecord>()
                        .ge(AlarmRecord.AlarmTime, todayStart)
        );
        
        // 待处理告警数
        long pendingAlarms = alarmRecordMapper.selectCount(
                new QueryWrapper<AlarmRecord>()
                        .eq(AlarmRecord.Status, AlarmStatusEnum.PENDING.getValue())
        );
        
        // 已处理告警数（已关闭和误报）
        long processedAlarms = alarmRecordMapper.selectCount(
                new QueryWrapper<AlarmRecord>()
                        .in(AlarmRecord.Status, AlarmStatusEnum.CLOSED.getValue(), AlarmStatusEnum.FALSE_ALARM.getValue())
        );
        
        return KeyMetricsVO.builder()
                .totalDevices(totalDevices)
                .onlineDevices(onlineDevices)
                .onlineRate(onlineRate)
                .todayAlarms(todayAlarms)
                .pendingAlarms(pendingAlarms)
                .processedAlarms(processedAlarms)
                .build();
    }

    @Override
    public AlarmDistributionVO getAlarmDistribution() {
        // 查询所有算法
        List<AlgAlgorithm> algorithms = algAlgorithmMapper.selectList(null);

        // 查询告警分布（分组统计）
        QueryWrapper<AlarmRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(AlarmRecord.AlgorithmId, "COUNT(*) as count")
                .groupBy(AlarmRecord.AlgorithmId);
        List<Map<String, Object>> typeCountList = alarmRecordMapper.selectMaps(queryWrapper);

        // 将统计结果转为 Map<algorithmId, count>
        java.util.Map<Long, Long> countMap = typeCountList.stream()
                .filter(map -> map.get(AlarmRecord.AlgorithmId) != null)
                .collect(Collectors.toMap(
                        map -> ((Number) map.get(AlarmRecord.AlgorithmId)).longValue(),
                        map -> ((Number) map.get("count")).longValue()
                ));

        // 计算总数
        long total = countMap.values().stream().mapToLong(Long::longValue).sum();

        // 组装VO，覆盖所有算法，即使没有告警也返回，名称按算法名称
        List<AlarmDistributionVO.AlarmTypeItem> items = new ArrayList<>();
        for (AlgAlgorithm algorithm : algorithms) {
            AlarmDistributionVO.AlarmTypeItem item = new AlarmDistributionVO.AlarmTypeItem();
            item.setAlgorithmId(algorithm.getId());
            item.setName(algorithm.getName());
            item.setShortName(algorithm.getShortName());
            long count = countMap.getOrDefault(algorithm.getId(), 0L);
            item.setCount(count);
            double percentage = total > 0 ? (double) count / total * 100 : 0;
            item.setPercentage(percentage);
            items.add(item);
        }

        AlarmDistributionVO vo = new AlarmDistributionVO();
        vo.setList(items);
        return vo;
    }

    @Override
    public DashboardSummaryVO getDashboardSummary() {
        DashboardSummaryVO summary = new DashboardSummaryVO();
        summary.setAlarmEfficiency(getAlarmEfficiency());
        summary.setRealtimeAlarms(getRealtimeAlarms(10));
        summary.setAlarmTrend(getAlarmTrend());
        summary.setKeyMetrics(getKeyMetrics());
        summary.setAlarmDistribution(getAlarmDistribution());
        return summary;
    }
}